
#import "JMNetworkUtils.h"
#import "AFNetworking.h"
#import "JMCommonUtils.h"
#import "FFLoading.h"
#import "Definition.h"
#import "MBProgressHUD.h"

#define HUDTAG 52451000 + 20221212
#define HUDTEXTTAG 52451001 + 20221212
#define TOASTTAG 52451002 + 20221212

@interface JMNetworkUtils () {
    //初始化单例类
    AFHTTPSessionManager *manager;
    //https://codehunter.cc/a/objective-c/afnetworking-3-0-afhttpsessionmanager-using-nsoperation
    //https://stackoverflow.com/questions/34753816/afnetworking-3-0-afhttpsessionmanager-using-nsoperation
    //dispatch_group_t group;
}

@property(assign, atomic) int requestsCount;

@end

@implementation JMNetworkUtils

- (void)dealloc {
}

+ (JMNetworkUtils *)sharedInstance {
    static JMNetworkUtils *Instance;
    @synchronized(Instance) {
        if (!Instance) {
            Instance = [[JMNetworkUtils alloc] init];
        }
    }
    return Instance;
}

- (id)init {
    self = [super init];
    if (self) {
        //初始化单例类
        manager = [AFHTTPSessionManager manager];
        [self addObservers];

        /**
        group = dispatch_group_create();
        dispatch_group_notify(group, dispatch_get_main_queue(), ^{
          NSLog(@"All done");
        });

        dispatch_group_t downloadGroup = dispatch_group_create();
        for (int i = 0; i < 10; i++) {
            dispatch_group_enter(downloadGroup);
            [HttpsUtils doHttpPost:@""
                header:@{}
                param:@{}
                success:^(NSDictionary *responseObject, BOOL success, NSString *msg) {
                  dispatch_group_leave(downloadGroup);
                }
                fail:^(NSError *error) {
                  dispatch_group_leave(downloadGroup);
                }];
        }

        dispatch_group_notify(downloadGroup, dispatch_get_main_queue(), ^{
          NSLog(@"end");
        });
         */
    }
    return self;
}

#pragma mark -

//显示 toast
+ (void)ShowToastByContent:(NSString *)content afterDelay:(NSInteger)delay actionEnabled:(bool)isEnabled withBlock:(void (^)(void))completionBlock {
    [[JMNetworkUtils sharedInstance] ShowToastByContent:content afterDelay:delay actionEnabled:isEnabled withBlock:completionBlock];
}

+ (void)showHudWithText:(NSString *)textString {
    [[JMNetworkUtils sharedInstance] showHudWithText:textString];
}

+ (void)showAutomicHiddenHudText:(NSString *)textString {
    [[JMNetworkUtils sharedInstance] showAutomicHiddenHudText:textString];
}

+ (void)showHudWithText:(NSString *)textString duration:(NSTimeInterval)duration {
    [[JMNetworkUtils sharedInstance] showHudWithText:textString duration:duration];
}

+ (void)dismiss {
    dispatch_block_t main_queue_block = ^{
      [[JMNetworkUtils sharedInstance] dismissALL];
    };
    if ([NSThread isMainThread]) {
        main_queue_block();
    } else {
        dispatch_async(dispatch_get_main_queue(), ^{
          main_queue_block();
        });
    }
}

#pragma mark -

+ (void)showAlertView:(NSString *)title withOkBlock:(void (^)(void))okBlock withCancelBlock:(void (^)(void))cancelBlock {
    dispatch_block_t block = ^{
      UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleAlert];
      UIViewController *rootVC = [UIApplication sharedApplication].keyWindow.rootViewController;
      while (rootVC.presentedViewController) {
          rootVC = rootVC.presentedViewController;
      }
      //
      UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"确定"
                                                         style:UIAlertActionStyleDefault
                                                       handler:^(UIAlertAction *_Nonnull action) {
                                                         if (okBlock) {
                                                             okBlock();
                                                         }
                                                       }];
      //
      UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消"
                                                             style:UIAlertActionStyleCancel
                                                           handler:^(UIAlertAction *_Nonnull action) {
                                                             if (cancelBlock) {
                                                                 cancelBlock();
                                                             }
                                                           }];

      //修改背景色
      UIView *subview = alertVC.view.subviews.firstObject.subviews.firstObject.subviews.firstObject;
      UIColor *color = [UIColor colorWithRed:45 / 255.0 green:44 / 255.0 blue:43 / 255.0 alpha:0.8];
      subview.backgroundColor = color;

      /*
       //修改UIAlertController 标题以及内容 颜色以及标题字号大小
       let str:NSMutableAttributedString = NSMutableAttributedString.init(string:"修改家庭名称")
       str.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.init(hex:"#D3D3D3")!, range:NSRange(location: 0,length:6))
       str.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.orange, range:NSRange(location: 0,length:2))
       str.addAttribute(NSAttributedString.Key.font, value: UIFont.systemFont(ofSize: 12), range: NSRange(location: 0,length:2))
       //修改标题内容
       alertVC.setValue(str, forKey:"attributedTitle")
       //修改messgage内容
       alertVC.setValue(str, forKey:"attributedMessage")
       */
      NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:title];
      [str addAttribute:NSForegroundColorAttributeName value:UIColor.whiteColor range:NSMakeRange(0, title.length)];
      [alertVC setValue:str forKey:@"attributedTitle"];

      /*
       //确定&取消按钮颜色设置
       cancelAction.setValue(UIColor.init(hex:"#D3D3D3", alpha: 0.7), forKey: "_titleTextColor")
       */
      [cancelAction setValue:UIColor.whiteColor forKey:@"_titleTextColor"];
      [okAction setValue:[UIColor colorWithRed:204 / 255.0 green:166 / 255.0 blue:127 / 255.0 alpha:1.0] forKey:@"_titleTextColor"];

      //放在最后面
      [alertVC addAction:okAction];
      [alertVC addAction:cancelAction];

      [rootVC presentViewController:alertVC animated:true completion:nil];
    };
    if ([NSThread isMainThread]) {
        block();
    } else {
        dispatch_async(dispatch_get_main_queue(), ^{
          block();
        });
    }
}

#pragma mark - Observers

- (void)addObservers {
    NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld;
    [self addObserver:self forKeyPath:@"requestsCount" options:options context:nil];
}

- (void)removeObservers {
    [self removeObserver:self forKeyPath:@"requestsCount"];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if ([self requestsCount] == 0) {
    }
    int new = [ change[@"new"] intValue ];
    if (new == 0) {
        [self removeHud];
        if (self.completionCallBack) {
            self.completionCallBack();
            self.completionCallBack = nil;
        }
    }
}

#pragma mark - network

- (void)connectWithUrl:(NSString *)url
            parameters:(NSDictionary *)dic
               showHud:(bool)isShowed
            showErrHud:(bool)isShowedErr
            withMethod:(NSString *)Method
               success:(void (^)(id responseObject, bool isSuccess))success
               failure:(void (^)(NSError *error))failure {
    @weakify(self);
    //
    if (![JMCommonUtils isNetworkReachable]) {
        [self showAutomicHiddenHudText:@"网络异常，请检查网络连接"];

        dispatch_block_t main_queue_block = ^{
          if (failure) {
              NSDictionary *info = @{
                  @"message" : @"网络异常，请检查网络连接",
                  NSLocalizedDescriptionKey : @"网络异常，请检查网络连接",
              };
              NSError *err = [NSError errorWithDomain:@"" code:0 userInfo:info];
              failure(err);
          }
        };
        if ([NSThread isMainThread]) {
            main_queue_block();
        } else {
            dispatch_async(dispatch_get_main_queue(), ^{
              main_queue_block();
            });
        }

        return;
    }

    //成功回调
    void (^successBlock)(NSURLSessionDataTask *_Nonnull task, id _Nullable responseObject) = ^(NSURLSessionDataTask *_Nonnull task, id _Nullable responseObject) {
      //
      @strongify(self);

      //注意：responseObject:请求成功返回的响应结果（AFN内部已经把响应体转换为OC对象，通常是字典或数组）
      bool flag = false;
      NSDictionary *dic = (NSDictionary *)responseObject;
      if ([dic[@"code"] intValue] == 200) {
          flag = true;
          [self removeHud];
      } else if ([dic[@"code"] intValue] == 600 || [dic[@"code"] intValue] == 601) {
          NSString *message = dic[@"message"];
          if (message == (NSString *)[NSNull null] || !message || message.length == 0) {
              [self showAutomicHiddenHudText:@"网络异常，请检查网络连接"];
          } else {
              [self showAutomicHiddenHudText:dic[@"message"]];
          }
          //被迫下线
          [[NSNotificationCenter defaultCenter] postNotificationName:@"AcountForceLogout" object:nil];
      } else {
          NSString *message = dic[@"message"];
          if (message == (NSString *)[NSNull null] || !message || message.length == 0) {
              if (isShowedErr) {
                  [self showAutomicHiddenHudText:@"网络异常，请检查网络连接"];
              }
          } else {
              if ([message containsString:@"登录账号"]) {
                  [self showAutomicHiddenHudText:dic[@"message"]];
                  [[NSNotificationCenter defaultCenter] postNotificationName:@"AcountForceLogout" object:nil];
              } else {
                  if (isShowedErr) {
                      [self showAutomicHiddenHudText:dic[@"message"]];
                  }
              }
          }
      }

      dispatch_block_t main_queue_block = ^{
        if (success) {
            if (flag) {
                success(dic[@"data"], flag);
            } else {
                success(dic, flag);
            }
        }

        [self setRequestsCount:[self requestsCount] - 1];
      };
      if ([NSThread isMainThread]) {
          main_queue_block();
      } else {
          dispatch_async(dispatch_get_main_queue(), ^{
            main_queue_block();
          });
      }
    };

    //失败回调
    void (^failureBlock)(NSURLSessionDataTask *_Nullable task, NSError *_Nonnull error) = ^(NSURLSessionDataTask *_Nullable task, NSError *_Nonnull error) {
      //
      @strongify(self);

      if (isShowedErr) {
          //NSLog(@"请求失败---%@", error);
          [self showAutomicHiddenHudText:error.description];
      }

      dispatch_block_t main_queue_block = ^{
        if (failure) {
            failure(error);
        }

        [self setRequestsCount:[self requestsCount] - 1];
      };
      if ([NSThread isMainThread]) {
          main_queue_block();
      } else {
          dispatch_async(dispatch_get_main_queue(), ^{
            main_queue_block();
          });
      }
    };

    /**
     方式一
     [manager.operationQueue addOperationWithBlock:^ {
     NSLog(@"%lu", (unsigned long)manager.operationQueue.operationCount);
     }];
     */
    //

    //方式二
    NSBlockOperation *ope = [NSBlockOperation blockOperationWithBlock:^{
      //
      @strongify(self);

      [self setRequestsCount:[self requestsCount] + 1];

      //设置loading
      if (isShowed) {
          [self showHudWithText:@""];
      }

      //根据不通的请求方式,设置序列化方式
      {
          //设置序列化方式,设置完才能添加 header 和 body
          if ([Method isEqualToString:@"POST"]) {
              //初始化单例类
              //AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
              //设置非校验证书模式
              self->manager.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
              self->manager.securityPolicy.allowInvalidCertificates = YES;
              [self->manager.securityPolicy setValidatesDomainName:NO];

              //序列化
              //请求的序列化
              self->manager.requestSerializer = [AFJSONRequestSerializer serializer];
              //回复的序列化
              self->manager.responseSerializer = [AFJSONResponseSerializer serializer];

              //如果返回的是XML，那么告诉AFN，响应的时候使用XML的方式解析
              // manager.responseSerializer = [AFXMLParserResponseSerializer serializer];
              //如果返回的就是二进制数据，那么采用默认二进制的方式来解析数据
              // manager.responseSerializer = [AFHTTPResponseSerializer serializer];
              //采用JSON的方式来解析数据
              // manager.responseSerializer = [AFJSONResponseSerializer serializer];

              //告诉AFN，再序列化服务器返回的数据的时候，支持此种类型
              //[AFJSONResponseSerializer serializer].acceptableContentTypes = [NSSet setWithObject:@"application/json"];
          }

          if ([Method isEqualToString:@"UPLOAD"]) {
              //序列化
              //请求的序列化
              self->manager.requestSerializer = [AFHTTPRequestSerializer serializer];
              //回复的序列化
              self->manager.responseSerializer = [AFJSONResponseSerializer serializer];

              self->manager.responseSerializer.acceptableContentTypes =
                  [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", @"text/html", @"text/plain", @"image/jpeg", @"image/png", nil];

              //[self->manager.requestSerializer setValue:@"multipart/form-data"                     forHTTPHeaderField:@"Content-Type"];
          }
      }

      //设置 Header,序列化完才能设置 header 和 body
      {
          /*
           {
           "Headers":{
           "Authorization":"Bearer '+token"
           },
           "Body":{
           "id":"abc",
           "status":1
           }
           }
           */

          //设置请求头
          NSDictionary *Headers = dic[@"Headers"];
          NSMutableDictionary *mdic_headers = [NSMutableDictionary dictionary];

#define KEY_ACCOUNT_TOKEN @"accountToken"
          NSString *token = [[NSUserDefaults standardUserDefaults] stringForKey:KEY_ACCOUNT_TOKEN];
          NSString *Authorization = [NSString stringWithFormat:@"Bearer %@", token];

          mdic_headers[@"Authorization"] = Authorization;

          if (Headers) {
              [mdic_headers addEntriesFromDictionary:Headers];
          }

          for (NSString *key in mdic_headers) {
              [self->manager.requestSerializer setValue:mdic_headers[key] forHTTPHeaderField:key];
          }
      }

      //设置 body
      NSMutableDictionary *bodyDic = [NSMutableDictionary dictionary];
      {
          //赋值
          NSDictionary *Body = dic[@"Body"];
          if (Body) {
              [bodyDic setDictionary:Body];
          }
      }

      //设置 url
      NSString *urlString = url;

      if ([Method isEqualToString:@"POST"]) {
          //3.发送POST请求
          [self->manager POST:urlString
              parameters:bodyDic
              progress:nil
              success:^(NSURLSessionDataTask *_Nonnull task, id _Nullable responseObject) {
                successBlock(task, responseObject);
              }
              failure:^(NSURLSessionDataTask *_Nullable task, NSError *_Nonnull error) {
                failureBlock(task, error);
              }];
      }

      if ([Method isEqualToString:@"UPLOAD"]) {
          NSMutableDictionary *postDic = [NSMutableDictionary dictionary];
          NSMutableDictionary *fileDic = [NSMutableDictionary dictionary];
          NSMutableDictionary *dataDic = [NSMutableDictionary dictionary];
          NSFileManager *fileManager = [NSFileManager defaultManager];

          for (NSString *key in bodyDic) {
              id value = bodyDic[key];
              if ([value isKindOfClass:NSData.class]) {
                  dataDic[key] = value;
              } else {
                  if ([value isKindOfClass:NSString.class]) {
                      bool success = [fileManager fileExistsAtPath:value];
                      if (success) {
                          fileDic[key] = value;
                      } else {
                          postDic[key] = value;
                      }
                  } else {
                      postDic[key] = value;
                  }
              }
          }

          [self->manager POST:urlString
              parameters:postDic
              constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {
                for (NSString *key in fileDic) {
                    NSString *str_mimeType = @"";
                    NSString *path = fileDic[key];
                    if ([path hasSuffix:@"png"]) {
                        str_mimeType = @"image/png";
                    }
                    if ([path hasSuffix:@"jpg"] || [path hasSuffix:@"jpeg"]) {
                        str_mimeType = @"image/jpeg";
                    }
                    NSURL *url = [NSURL fileURLWithPath:path];

                    [formData appendPartWithFileURL:url name:@"file" fileName:key mimeType:str_mimeType error:nil];
                }

                for (NSString *key in dataDic) {
                    NSData *data = dataDic[key];
                    [formData appendPartWithFormData:data name:key];
                }
              }
              progress:^(NSProgress *_Nonnull uploadProgress) {
                NSLog(@"上传进度：%f", uploadProgress.fractionCompleted);
              }
              success:^(NSURLSessionDataTask *_Nonnull task, id _Nullable responseObject) {
                NSLog(@"上传完成：%@", responseObject);

                //
                @strongify(self);

                //注意：responseObject:请求成功返回的响应结果（AFN内部已经把响应体转换为OC对象，通常是字典或数组）
                bool flag = false;
                NSDictionary *dic = (NSDictionary *)responseObject;

                flag = true;
                [self removeHud];

                dispatch_block_t main_queue_block = ^{
                  if (success) {
                      success(dic, flag);
                  }

                  [self setRequestsCount:[self requestsCount] - 1];
                };
                if ([NSThread isMainThread]) {
                    main_queue_block();
                } else {
                    dispatch_async(dispatch_get_main_queue(), ^{
                      main_queue_block();
                    });
                }
              }
              failure:^(NSURLSessionDataTask *_Nullable task, NSError *_Nonnull error) {
                failureBlock(task, error);
              }];
      }
    }];
    [manager.operationQueue addOperation:ope];
}

- (void)connectWithUrl:(NSString *)url
            parameters:(NSDictionary *_Nullable)dic
               showHud:(bool)isShowed
            withMethod:(NSString *)Method
               success:(void (^_Nullable)(id responseObject, bool isSuccess))success
               failure:(void (^_Nullable)(NSError *error))failure {
    [self connectWithUrl:url
              parameters:dic
                 showHud:isShowed
              showErrHud:true
              withMethod:Method
                 success:success
                 failure:failure];
}

- (void)connectWithUrl:(NSString *)url
            parameters:(NSDictionary *)dic
               showHud:(bool)isShowed
               success:(void (^)(id responseObject, bool isSuccess))success
               failure:(void (^)(NSError *error))failure {
    [self connectWithUrl:url
              parameters:dic
                 showHud:isShowed
              withMethod:@"POST"
                 success:success
                 failure:failure];
}

- (void)connectWithUrl:(NSString *)url
            parameters:(NSDictionary *)dic
               showHud:(bool)isShowed
            showErrHud:(bool)isShowedErr
               success:(void (^)(id responseObject, bool isSuccess))success
               failure:(void (^)(NSError *error))failure {
    [self connectWithUrl:url
              parameters:dic
                 showHud:isShowed
              showErrHud:isShowedErr
              withMethod:@"POST"
                 success:success
                 failure:failure];
}

#pragma mark - alert

//显示 toast
- (void)ShowToastByContent:(NSString *)content afterDelay:(NSInteger)delay actionEnabled:(bool)isEnabled withBlock:(void (^)(void))completionBlock {
    dispatch_block_t block = ^{
      [self dismissWithTag:TOASTTAG];
      UIWindow *win = [UIApplication sharedApplication].keyWindow;
      if (!win) {
          win = [UIApplication sharedApplication].windows[0];
      }
      MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:win animated:YES];
      hud.tag = TOASTTAG;
      hud.mode = MBProgressHUDModeText;
      hud.userInteractionEnabled = isEnabled;
      hud.detailsLabel.text = content;
      hud.detailsLabel.font = [UIFont systemFontOfSize:14];
      hud.detailsLabel.textColor = [UIColor colorWithWhite:0.8f alpha:0.8f];
      hud.margin = 10.f;
      hud.minSize = CGSizeMake(200, 30);
      CGFloat offSetY = win.bounds.size.height / 2 - 90;
      hud.offset = CGPointMake(hud.offset.x, offSetY);
      hud.removeFromSuperViewOnHide = YES;
      hud.bezelView.style = MBProgressHUDBackgroundStyleSolidColor;
      //提示框背景色
      hud.bezelView.color = [UIColor colorWithWhite:0.5f alpha:1.0];
      hud.backgroundView.style = MBProgressHUDBackgroundStyleSolidColor;
      //蒙层的颜色
      hud.backgroundView.color = [UIColor colorWithWhite:0.f alpha:0.2f];
      [hud hideAnimated:true afterDelay:delay];
      hud.completionBlock = ^{
        if (completionBlock) {
            completionBlock();
        }
      };
    };
    if ([NSThread isMainThread]) {
        block();
    } else {
        dispatch_async(dispatch_get_main_queue(), ^{
          block();
        });
    }
}

- (void)showHudWithText:(NSString *)textString {
    dispatch_block_t block = ^{
      [self dismissWithTag:HUDTAG];
      UIWindow *win = [UIApplication sharedApplication].keyWindow;
      if (!win) {
          win = [UIApplication sharedApplication].windows[0];
      }
      MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:win animated:YES];
      hud.tag = HUDTAG;
      hud.mode = MBProgressHUDModeIndeterminate;
      hud.userInteractionEnabled = true;

      hud.detailsLabel.font = [UIFont boldSystemFontOfSize:16];
      hud.detailsLabel.text = textString;

      hud.removeFromSuperViewOnHide = YES;
    };
    if ([NSThread isMainThread]) {
        block();
    } else {
        dispatch_async(dispatch_get_main_queue(), ^{
          block();
        });
    }
}

- (void)showAutomicHiddenHudText:(NSString *)textString {
    [self showHudWithText:textString duration:2.0f];
}

- (void)showHudWithText:(NSString *)textString duration:(NSTimeInterval)duration {
    dispatch_block_t block = ^{
      [self dismissWithTag:HUDTEXTTAG];
      UIWindow *win = [UIApplication sharedApplication].keyWindow;
      if (!win) {
          win = [UIApplication sharedApplication].windows[0];
      }
      MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:win animated:YES];
      hud.tag = HUDTEXTTAG;
      hud.mode = MBProgressHUDModeText;
      hud.userInteractionEnabled = true;
      hud.detailsLabel.text = textString;
      hud.detailsLabel.font = [UIFont systemFontOfSize:16];
      hud.removeFromSuperViewOnHide = YES;
      [hud hideAnimated:true afterDelay:duration];
    };
    if ([NSThread isMainThread]) {
        block();
    } else {
        dispatch_async(dispatch_get_main_queue(), ^{
          block();
        });
    }
}

- (void)removeHud {
    if ([self requestsCount] != 0) {
        return;
    }
    [self dismissWithTag:HUDTAG];
}

- (void)dismissWithTag:(int)viewTag {
    if ([NSThread isMainThread]) {
        [self performDismissWithTag:viewTag];
    } else {
        dispatch_async(dispatch_get_main_queue(), ^{
          [self performDismissWithTag:viewTag];
        });
    }
}

- (void)performDismissWithTag:(int)viewTag {
    [FFLoading dismiss];

    UIWindow *win = [UIApplication sharedApplication].keyWindow;
    if (!win) {
        win = [UIApplication sharedApplication].windows[0];
    }

    //使用 while 循环移除所有具有相同标签的视图
    UIView *view;
    while ((view = [win viewWithTag:viewTag])) {
        [view removeFromSuperview];
        //NSLog(@"已移除标签为 %d 的视图", viewTag);
    }
}

- (void)dismissALL {
    [self dismissWithTag:HUDTAG];
    [self dismissWithTag:HUDTEXTTAG];
    [self dismissWithTag:TOASTTAG];
}

@end

/**
//  ViewController.m

#import "ViewController.h"
#import "AFNetworking.h"
#import "AFHTTPSessionOperation.h"

@interface ViewController ()

@end

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    NSString *urlString1 = @"...";
    NSString *urlString2 = @"...";
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    // manager.operationQueue
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    queue.name = @"AFHTTPSessionManager queue";
    NSOperation *completionOperation = [NSBlockOperation blockOperationWithBlock:^{
      NSLog(@"All done");
    }];
    NSOperation *op1 = [AFHTTPSessionOperation operationWithManager:manager
        HTTPMethod:@"GET"
        URLString:urlString1
        parameters:nil
        uploadProgress:nil
        downloadProgress:nil
        success:^(NSURLSessionDataTask *task, id responseObject) {
          NSLog(@"finished 1");
        }
        failure:^(NSURLSessionDataTask *task, NSError *error) {
          NSLog(@"failed 1 - error = %@", error.localizedDescription);
        }];
    [completionOperation addDependency:op1];
    NSOperation *op2 = [AFHTTPSessionOperation operationWithManager:manager
        HTTPMethod:@"GET"
        URLString:urlString2
        parameters:nil
        uploadProgress:nil
        downloadProgress:nil
        success:^(NSURLSessionDataTask *task, id responseObject) {
          NSLog(@"finished 2");
        }
        failure:^(NSURLSessionDataTask *task, NSError *error) {
          NSLog(@"failed 2 - error = %@", error.localizedDescription);
        }];
    [completionOperation addDependency:op2];
    [queue addOperations:@[ op1, op2 ] waitUntilFinished:false];
    [[NSOperationQueue mainQueue] addOperation:completionOperation];  // do this on whatever queue you want, but often you're updating UI or model objects, in which case you'd use the main queue
}
@end

// ViewController.m

#import "ViewController.h"
#import "AFNetworking.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    NSString *urlString1 = @"...";
    NSString *urlString2 = @"...";
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    dispatch_group_t group = dispatch_group_create();
    dispatch_group_enter(group);
    [manager GET:urlString1
        parameters:nil
        progress:nil
        success:^(NSURLSessionDataTask *_Nonnull task, id _Nullable responseObject) {
          NSLog(@"finished 1");
          dispatch_group_leave(group);
        }
        failure:^(NSURLSessionDataTask *_Nullable task, NSError *_Nonnull error) {
          NSLog(@"failed 1 - error = %@", error.localizedDescription);
          dispatch_group_leave(group);
        }];
    dispatch_group_enter(group);
    [manager GET:urlString2
        parameters:nil
        progress:nil
        success:^(NSURLSessionDataTask *_Nonnull task, id _Nullable responseObject) {
          NSLog(@"finished 2");
          dispatch_group_leave(group);
        }
        failure:^(NSURLSessionDataTask *_Nullable task, NSError *_Nonnull error) {
          NSLog(@"failed 2 - error = %@", error.localizedDescription);
          dispatch_group_leave(group);
        }];
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
      NSLog(@"All done");
    });
}
@end
*/
